#ifndef C_HASHMAP_H
#define C_HASHMAP_H

typedef struct map_entry {
    void* key;
    void* val;
    struct map_entry* next;
} map_entry;

typedef unsigned int (*hash_Fn)(void* key);
typedef int (*equal_Fn)(void* k1, void* k2);
typedef struct hash_map {
    hash_Fn hashf;
    equal_Fn equalf;
    map_entry** bucket;
    unsigned int mask; // bucket位置掩码，便于快速计算，值为(2^n -1),即8/16/32/64位的全1二进制值
    int cur;           // 用于map_for_each 迭代时使用
    int used;          // 当前有多少个kv元素
    unsigned int size;
} hash_map;

void map_init(hash_map* m, hash_Fn hash_fn, equal_Fn equal_fn, unsigned int bucket_size);
int map_put(hash_map* m, map_entry* e);
map_entry* map_get(hash_map* m, void* key);
map_entry* map_del(hash_map* m, void* key);

#define get_next_collision(m, e)                                  \
    {                                                             \
        while (m->cur < m->size && m->bucket[m->cur] == NULL)     \
            m->cur++;                                             \
        e = (m->cur <= m->size - 1 ? m->bucket[m->cur++] : NULL); \
    }

#define map_for_each(m, e)    \
    m->cur = 0;               \
    get_next_collision(m, e); \
    for (; (e == NULL ? ((get_next_collision(m, e)) != NULL) : 1); e = e->next)

unsigned int time33(char* str);
/* MurmurHash2, by Austin Appleby
 * Note - This code makes a few assumptions about how your machine behaves -
 * 1. We can read a 4-byte value from any address without crashing
 * 2. sizeof(int) == 4
 *
 * And it has a few limitations -
 *
 * 1. It will not work incrementally.
 * 2. It will not produce the same results on little-endian and big-endian
 *    machines.
 */
unsigned int murmur_hash(const void* key, int len);

/* Thomas Wang's 32 bit Mix Function */
unsigned int dict_int_hash(unsigned int key);

#endif // C_HASHMAP_H